/*
 * Copyright © 2017 eqxiu.com 北京中网易企秀科技有限公司  All rights reserved.
 */
package cn.hermit.data.json.model;

import cn.hermit.util.ReflectionUtils;
import cn.hermit.util.StringUtils;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Java Model of JSON Object
 *
 * @author Jack Gao (Chinese name : GAO JIANGUO, Email : linux.gjg@gmail.com)
 * @date 13 Jun, 2014
 */
public class JSONObject extends JSONDocument {

    /**
     *
     */
    private static final long serialVersionUID = 3912584644848142051L;

    Map<String, JSONDocument> entries;

    JSONObject() {
    }

    /**
     * Clear JSON Entries from JSON Object
     */
    public void clear() {
        entries.clear();
    }

    /**
     * @return Iterator for JSON Entries in JSON Object
     */
    public Iterator<Entry<String, JSONDocument>> entryIterator() {
        return entries.entrySet().iterator();
    }

    /**
     * @return Iterator for JSON keys in JSON Object
     */
    public Iterator<String> keyIterator() {
        return entries.keySet().iterator();
    }

    /**
     * @return Iterator for JSON values in JSON Object
     */
    public Iterator<JSONDocument> valueIterator() {
        return entries.values().iterator();
    }

    /**
     * Check if the JSON Object has a key
     *
     * @param key JSON key for checking
     * @return
     */
    public boolean containsKey(String key) {
        return entries.containsKey(key);
    }

    /**
     * Remove JSON Entry by key.
     *
     * @param key JSON key for removing
     * @return The removed JSON Entry value in JSON Object
     */
    public JSONDocument removeKey(String key) {
        return this.entries.remove(key);
    }

    /**
     * Get JSON Entry value from JSON Object by key.
     *
     * @param key JSON key for getting
     * @return
     */
    public JSONDocument getValue(String key) {
        return entries.get(key);
    }

    /**
     * @return JSON Entries size in JSON Object
     */
    public int size() {
        return entries.size();
    }

    /**
     * Serialize JSON Object to JSON string without tab indents
     */
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('{');
        if (!ReflectionUtils.isEmpty(entries)) {

        }
        Iterator<String> iter = entries.keySet().iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            String keyTxt = key;
            sb.append('"').append(keyTxt).append('"');
            sb.append(':');
            JSONDocument value = entries.get(key);
            if (JSONValue.class.isInstance(value)) {
                JSONValue jsv = (JSONValue) value;
                if (jsv.isText()) {
                    sb.append('"');
                }
                sb.append(value);
                if (jsv.isText()) {
                    sb.append('"');
                }
            } else {
                sb.append(value);
            }
            if (iter.hasNext())
                sb.append(',');
        }
        sb.append('}');
        return sb.toString();
    }

    String toFormatString(int depth, String newLineFeed, boolean isTop) {
        StringBuilder sb = new StringBuilder();
        if (isTop) {
            sb.append(StringUtils.tabs(depth));
        }
        sb.append('{');
        if (!ReflectionUtils.isEmpty(entries)) {
            sb.append(newLineFeed);
            Iterator<String> iter = entries.keySet().iterator();
            while (iter.hasNext()) {
                String key = iter.next();
                String keyTxt = key;
                sb.append(StringUtils.tabs(depth + 1)).append('"').append(keyTxt).append('"');
                sb.append(':');
                JSONDocument value = entries.get(key);
                if (JSONValue.class.isInstance(value)) {
                    JSONValue jsv = (JSONValue) value;
                    if (jsv.isText()) {
                        sb.append('"');
                    }
                    sb.append(value.toString());
                    if (jsv.isText()) {
                        sb.append('"');
                    }
                } else {
                    sb.append(value.toFormatString(depth + 1, newLineFeed, false));
                }
                if (iter.hasNext())
                    sb.append(',').append(newLineFeed);
            }
            sb.append(newLineFeed).append(StringUtils.tabs(depth));
        }
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean isArray() {
        return false;
    }

    @Override
    public boolean isObject() {
        return true;
    }

    @Override
    public boolean isValue() {
        return false;
    }

    @Override
    public boolean isTextValue() {
        return false;
    }
}